package qj.tool.gae.dump;

import static qj.util.SwingUtil.*;

import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.swing.JPanel;

import net.sf.json.*;
import qj.tool.gae.db.AEDB;
import qj.util.*;
import qj.util.SwingUtil.RowAdder;
import qj.util.appCommon.swing.AppFrame;
import qj.util.funct.P0;

/**
 * BigData
 * @author ngan
 *
 */
@SuppressWarnings("unchecked")
public class DumpGaeC {

	DumpConnector connector;

	public DumpGaeC(String host) {
		connector = new DumpConnector(host);
	}

	public JPanel dumpPane(final AppFrame frame) {
		new File("data/dump").mkdirs();
		final JPanel listPanel = new JPanel();
		P0 refreshF = new P0() {public void e() {
			
			LinkedList<DumpUIItem> items = new LinkedList<DumpUIItem>();
			for (File file : new File("data/dump").listFiles()) {
				DumpUIItem dumpUIItem = new DumpUIItem(file.getName());
				dumpUIItem.onUpload = upload(file,frame);
				items.add(dumpUIItem);
			}

			listPanel.removeAll();
			RowAdder ra = rowAdder(listPanel);
			for (DumpUIItem dumpUIItem : items) {
				ra.whole(dumpUIItem.getComp());
			}
		}};
		
		ThreadUtil.run(refreshF);
		
		return panel_border(scrollPane(listPanel),panel(
				SwingUtil.btn("Download", startDownloadF(frame,refreshF))
				));
	}

	private P0 startDownloadF(AppFrame frame, final P0 refreshF) {
		return new P0() {public void e() {
			
			File dir = new File("data/dump/" + new SimpleDateFormat("yyMMdd_hhmmss").format(new Date()));
			dir.mkdirs();
			String profile = "essential";
			
			System.out.print("Downloading plan [" + connector.host +"]... ");
			String planStr = connector.getDumpPlan(profile);
			System.out.println("done.");

			FileUtil.writeToFile(planStr,new File(dir,"plan.json"));
			FileUtil.writeToFile(profile,new File(dir,"profile"));
			
			JSONArray plans = (JSONArray) JSONSerializer.toJSON(planStr);
			for (int i = 0; i < plans.size(); i++) {
				JSONObject dumpType = plans.getJSONObject(i);
				String entName = dumpType.getString("name");
				
				File typeDir = new File(dir,entName);
				typeDir.mkdir();
				
				// JSon
				System.out.print("Downloading json " + entName + " (" + ((List)dumpType.get("ids")).size() + ")... ");
				String jsonDump = connector.getJsonDump(entName, dumpType.getString("ids"));
				System.out.println("done.");
				FileUtil.writeToFile(jsonDump, new File(typeDir,"data.json"));
				
				// Blob
				List<String> blobFields = dumpType.getJSONArray("blobFields");
				for (String blobField : blobFields) {
					File blobFieldDir = new File(typeDir,blobField);
					blobFieldDir.mkdir();
					
					//TODO if isName type, have to use map for ids, the entity name cannot be used as file names
					
					List<JSONObject> jsonData = (List<JSONObject>) JSONSerializer.toJSON(jsonDump);
					for (JSONObject object : jsonData) {
						String id = object.getString("id");
						if (!(object.get(blobField) instanceof JSONNull)) {
							System.out.print("Downloading blob " + blobField + " for " + entName + "[" + id + "]... ");
							InputStream blobDump = connector.getBlobDump(entName,id,blobField);
							if (blobDump!=null) {
								FileUtil.writeToFile(blobDump, new File(blobFieldDir,AEDB.asciiKeyString(id)));
							}
							System.out.println("done.");
						}
					}
				}
			}

			System.out.println("Finish downloading.");
			refreshF.e();
		}};
	}
	
	private P0 upload(final File dir, AppFrame frame) {
		return new P0() {public void e() {
			connector.startUpload(FileUtil.readFileToString(new File(dir, "profile")));
//			JSONArray plans = (JSONArray) JSONSerializer.toJSON(FileUtil.readFileToString(new File(file,"plan.json")));
			for (File typeDir : dir.listFiles()) {
				if (!typeDir.isDirectory()) {
					continue;
				}
				
				String typeName = typeDir.getName();
				
				System.out.print("Uploading json " + typeName + "... ");
				connector.uploadJson(typeName,FileUtil.readFileToString(new File(typeDir,"data.json")));
				System.out.println("done.");
				
				for (File blobFieldDir : typeDir.listFiles()) {
					if (!blobFieldDir.isDirectory()) {
						continue;
					}
					
					String blobFieldName = blobFieldDir.getName();
					
					for (File blobFile : blobFieldDir.listFiles()) {
						String fileName = blobFile.getName();
						System.out.print("Uploading blob " + typeName + "#" + blobFieldName + " [" + AEDB.decodeAsciiKeyString(fileName) + "]... ");
						connector.uploadBlob(fileName, typeName, blobFieldName, FileUtil.readFileToBytes(blobFile));
						System.out.println("done.");
					}
				}
			}
			System.out.println("Finish uploading.");
		}};
	}
}
